<!DOCTYPE html>
<html>
<head>
    <title>Physics Diagram: Doppler Effect</title>
</head>
<body>

<canvas id="physicsCanvas" width="500" height="450"></canvas>

<script>
    const canvas = document.getElementById('physicsCanvas');
    const ctx = canvas.getContext('2d');

    // --- Style and Settings ---
    ctx.strokeStyle = 'black';
    ctx.fillStyle = 'black';
    ctx.lineWidth = 2;
    const mainFont = 'italic 22px serif';
    const subFont = 'italic 16px serif';

    // --- Helper Function ---
    function drawArrow(ctx, fromx, fromy, tox, toy) {
        const headlen = 10;
        const dx = tox - fromx;
        const dy = toy - fromy;
        const angle = Math.atan2(dy, dx);
        ctx.beginPath();
        ctx.moveTo(fromx, fromy);
        ctx.lineTo(tox, toy);
        ctx.moveTo(tox, toy);
        ctx.lineTo(tox - headlen * Math.cos(angle - Math.PI / 6), toy - headlen * Math.sin(angle - Math.PI / 6));
        ctx.moveTo(tox, toy);
        ctx.lineTo(tox - headlen * Math.cos(angle + Math.PI / 6), toy - headlen * Math.sin(angle + Math.PI / 6));
        ctx.stroke();
    }

    // --- Main Drawing ---

    // Coordinates and Dimensions
    const oX = 120;
    const oY = 100;
    const roadThickness = 10; // Half-width of the road channel

    // 1. Draw Roads
    ctx.beginPath();
    // Horizontal road
    ctx.moveTo(20, oY - roadThickness);
    ctx.lineTo(480, oY - roadThickness);
    ctx.moveTo(20, oY + roadThickness);
    ctx.lineTo(480, oY + roadThickness);
    // Vertical road
    ctx.moveTo(oX - roadThickness, 20);
    ctx.lineTo(oX - roadThickness, 430);
    ctx.moveTo(oX + roadThickness, 20);
    ctx.lineTo(oX + roadThickness, 430);
    ctx.stroke();

    // 2. Draw Intersection O
    ctx.beginPath();
    ctx.arc(oX, oY, 4, 0, 2 * Math.PI);
    ctx.fill();
    ctx.font = mainFont;
    ctx.textAlign = 'center';
    ctx.textBaseline = 'bottom';
    ctx.fillText('O', oX - 15, oY - 15);

    // 3. Draw Car A
    const carA = { x: 300, y: oY, w: 50, h: 20 };
    // Car body and hatching
    ctx.save();
    ctx.beginPath();
    ctx.rect(carA.x - carA.w / 2, carA.y - carA.h / 2, carA.w, carA.h);
    ctx.stroke();
    ctx.clip(); 
    ctx.lineWidth = 1.5;
    for (let i = -carA.h; i < carA.w; i += 6) {
        ctx.beginPath();
        ctx.moveTo(carA.x - carA.w / 2 + i, carA.y - carA.h / 2);
        ctx.lineTo(carA.x - carA.w / 2 + i + carA.h, carA.y + carA.h / 2);
        ctx.stroke();
    }
    ctx.restore();
    
    // Label A
    ctx.font = mainFont;
    ctx.textAlign = 'center';
    ctx.textBaseline = 'bottom';
    ctx.fillText('A', carA.x, carA.y - carA.h / 2 - 10);
    
    // Velocity Vector A
    ctx.lineWidth = 2;
    const vA_start_x = carA.x + carA.w / 2 + 15;
    const vA_end_x = vA_start_x + 50;
    drawArrow(ctx, vA_start_x, carA.y, vA_end_x, carA.y);
    
    // Label v_A
    const vA_label_x = vA_end_x + 10;
    const vA_label_y = carA.y;
    ctx.textAlign = 'left';
    ctx.textBaseline = 'middle';
    ctx.font = mainFont;
    ctx.fillText('v', vA_label_x, vA_label_y);
    const vA_v_width = ctx.measureText('v').width;
    ctx.font = subFont;
    ctx.fillText('A', vA_label_x + vA_v_width * 0.8, vA_label_y + 7);


    // 4. Draw Car B
    const carB = { x: oX, y: 300, w: 20, h: 50 };
    // Car body and hatching
    ctx.save();
    ctx.beginPath();
    ctx.rect(carB.x - carB.w / 2, carB.y - carB.h / 2, carB.w, carB.h);
    ctx.lineWidth = 2;
    ctx.stroke();
    ctx.clip();
    ctx.lineWidth = 1.5;
    for (let i = -carB.h; i < carB.w; i += 6) {
        ctx.beginPath();
        ctx.moveTo(carB.x - carB.w/2 + i, carB.y - carB.h/2);
        ctx.lineTo(carB.x - carB.w/2 + i + carB.h, carB.y + carB.h/2);
        ctx.stroke();
    }
    ctx.restore();
    
    // Label B
    ctx.font = mainFont;
    ctx.textAlign = 'right';
    ctx.textBaseline = 'middle';
    ctx.fillText('B', carB.x - carB.w / 2 - 10, carB.y);
    
    // Velocity vector B
    ctx.lineWidth = 2;
    const vB_start_y = carB.y + carB.h / 2 + 15;
    const vB_end_y = vB_start_y + 50;
    drawArrow(ctx, carB.x, vB_start_y, carB.x, vB_end_y);
    
    // Label v_B
    const vB_label_x = carB.x;
    const vB_label_y = vB_end_y + 20;
    // Manual subscript drawing for center alignment
    const v_char = 'v';
    ctx.font = mainFont;
    const vB_v_width = ctx.measureText(v_char).width;
    ctx.textAlign = 'left';
    ctx.textBaseline = 'middle';
    ctx.fillText(v_char, vB_label_x - vB_v_width / 2, vB_label_y);
    ctx.font = subFont;
    ctx.fillText('B', vB_label_x + vB_v_width / 2, vB_label_y + 7);

</script>

</body>
</html>